import numpy as np
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

from sklearn.metrics import confusion_matrix, roc_curve, auc, precision_recall_curve, average_precision_score
from sklearn.metrics import classification_report

try:
    # 尝试使用系统支持中文的字体
    plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'WenQuanYi Micro Hei', 'STHeiti', 'PingFang SC']
    plt.rcParams['axes.unicode_minus'] = False
except:
    font_path = '/System/Library/Fonts/PingFang.ttc'

    chinese_font = FontProperties(fname=font_path)
    plt.rcParams['font.family'] = chinese_font.get_name()
    plt.rcParams['axes.unicode_minus'] = False
def plot_accuracy(history):
    """绘制训练过程中的准确率变化"""
    plt.figure(figsize=(10, 6))
    plt.plot(history['accuracy'], label='Training Accuracy')
    plt.plot(history['val_accuracy'], label='Validation Accuracy')
    plt.title('Model Accuracy')
    plt.ylabel('Accuracy')
    plt.xlabel('Epoch')
    plt.legend()
    plt.grid(True)
    plt.show()


def plot_confusion_matrix(y_true, y_pred, classes, title='Confusion Matrix', cmap=plt.cm.Blues):
    """绘制混淆矩阵"""
    cm = confusion_matrix(y_true, y_pred)
    plt.figure(figsize=(8, 6))
    plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)

    fmt = 'd'
    thresh = cm.max() / 2.
    for i in range(cm.shape[0]):
        for j in range(cm.shape[1]):
            plt.text(j, i, format(cm[i, j], fmt),
                     ha="center", va="center",
                     color="white" if cm[i, j] > thresh else "black")

    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.tight_layout()
    plt.show()


def plot_roc_curve(y_true, y_probs, model_name):
    """绘制ROC曲线"""
    fpr, tpr, _ = roc_curve(y_true, y_probs)
    roc_auc = auc(fpr, tpr)

    plt.figure(figsize=(8, 6))
    plt.plot(fpr, tpr, color='darkorange', lw=2,
             label=f'{model_name} ROC curve (AUC = {roc_auc:.2f})')
    plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
    plt.xlim([0.0, 1.0])
    plt.ylim([0.0, 1.05])
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.title(f'{model_name} Receiver Operating Characteristic')
    plt.legend(loc="lower right")
    plt.grid(True)
    plt.show()


def calculate_overfitting_metrics(history):
    """计算过拟合指标"""
    if 'accuracy' in history and 'val_accuracy' in history:
        train_acc = history['accuracy'][-1]
        val_acc = history['val_accuracy'][-1]
        overfit_acc = train_acc - val_acc

        print(f"训练准确率: {train_acc:.4f}, 验证准确率: {val_acc:.4f}")
        print(f"准确率过拟合程度: {overfit_acc:.4f}")

    if 'loss' in history and 'val_loss' in history:
        train_loss = history['loss'][-1]
        val_loss = history['val_loss'][-1]
        overfit_loss = val_loss - train_loss

        print(f"训练损失: {train_loss:.4f}, 验证损失: {val_loss:.4f}")
        print(f"损失过拟合程度: {overfit_loss:.4f}")

    if overfit_acc > 0.05 or overfit_loss > 0.1:
        print("警告: 模型可能过拟合!")
    else:
        print("模型泛化能力良好")


def enhanced_classification_report(y_true, y_pred):
    """增强版分类报告"""
    # 标准分类报告
    print(classification_report(y_true, y_pred))

    # 计算额外指标
    cm = confusion_matrix(y_true, y_pred)
    tn, fp, fn, tp = cm.ravel()

    # 计算额外指标
    sensitivity = tp / (tp + fn)  # 召回率/敏感度
    specificity = tn / (tn + fp)  # 特异度
    fpr = fp / (fp + tn)  # 假阳性率
    fnr = fn / (fn + tp)  # 假阴性率

    print("\n额外指标:")
    print(f"敏感度 (Sensitivity): {sensitivity:.4f}")
    print(f"特异度 (Specificity): {specificity:.4f}")
    print(f"假阳性率 (FPR): {fpr:.4f}")
    print(f"假阴性率 (FNR): {fnr:.4f}")

    # 绘制PR曲线
    precision, recall, _ = precision_recall_curve(y_true, y_pred)
    avg_precision = average_precision_score(y_true, y_pred)

    plt.figure(figsize=(8, 6))
    plt.plot(recall, precision, lw=2, color='blue',
             label=f'Precision-Recall curve (AP={avg_precision:.2f})')
    plt.xlabel('Recall')
    plt.ylabel('Precision')
    plt.ylim([0.0, 1.05])
    plt.xlim([0.0, 1.0])
    plt.title('Precision-Recall Curve')
    plt.legend(loc="lower left")
    plt.grid(True)
    plt.show()
